讓開發者可以更容易的從母元件傳遞 state 到深層的子元件,並讓多個用到的 state 資料的元件可以隨著資料變動而更新。
const value = useContext(MyContext);
接收一個 context 物件,回傳該 context 內的值。
首先在 authContext.js 這隻檔案中建立 Context,順便可以把相關的 Provider 寫好。
// authContext.js
import React, { useState } from "react";
const AuthContext = React.createContext({
  isLoggedIn: false,
  onLogout: () => {},
  onLogin: (email, password) => {}
});
export const AuthContextProvider = (props) => {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const logoutHandler = () => {
    setIsLoggedIn(false);
  };
  const loginHandler = () => {
    setIsLoggedIn(true);
  };
  return (
    <AuthContext.Provider
      // 記得提供 context 給 Provider
      value={{
        isLoggedIn: isLoggedIn,
        onLogout: logoutHandler,
        onLogin: loginHandler
      }}
    >
      {props.children}
    </AuthContext.Provider>
  );
};
export default AuthContext;
然後可以把 Provider 包住你想傳遞的子元件,這裡範例包住 App 元件,實際上還是看需求,不一定要包到那麼父層的元件
// index.js
import ReactDOM from "react-dom";
import App from "./App";
import { AuthContextProvider } from "./authContext";
const rootElement = document.getElementById("root");
ReactDOM.render(
  <AuthContextProvider>
    <App />
  </AuthContextProvider>,
  rootElement
);
在 App.js 中透過 useContext 取得 context
// App.js
import React, { useContext } from "react";
import AuthContext from "./authContext";
const App = () => {
  const ctx = useContext(AuthContext);
  return (
    <>
      {!ctx.isLoggedIn && (
        <button onClick={() => ctx.onLogin("Tom", "123")}>Login</button>
      )}
      {ctx.isLoggedIn && <button onClick={() => ctx.onLogout()}>Logout</button>}
    </>
  );
};
export default App;
因為有用到 context 的元件在 context 更新時都會 re-render,所以比較不常變動的值才建議使用 context。
React.memo、useMemo 會在之後做介紹
根據這篇文章的結尾一段文章:
Context API 的本意並不是讓我們進行多層 state 的管理,而是讓多個共用資料的元件能夠方便隨著資料的更動而被更新。因此 React 才會讓使用 useContext 的元件都重新渲染